#include "user.srpc.h"

#include <unistd.h>
#include <signal.h>
#include <string>
#include <iostream>

#include <workflow/WFFacilities.h>
#include <workflow/MySQLResult.h>

#include <ppconsul/ppconsul.h>


using std::string;
using std::cout;
using std::endl;

using namespace srpc;

static WFFacilities::WaitGroup wait_group(1);

void sig_handler(int signo)
{
    printf("signo %d is coming.\n", signo);
	wait_group.done();
}

class UserServiceServiceImpl : public UserService::Service
{
public:
	void Sigup(ReqSignup *request, RespSignup *response, srpc::RPCContext *ctx) override
    {
        //1. 解析请求
        std::string username = request->username();
        std::string password = request->password();
        //2. 对用户的密码进行加密
        string salt("12345678");//(优化:随机生成)
        char * passwd  = crypt(password.c_str(), salt.c_str());
        string encodedpasswd(passwd);
        cout << "username:" << username << endl;
        cout << "password:" << password << endl;
        cout << "encode:" << encodedpasswd << endl;
        //3. 更新到数据库中
		string mysqlurl = "mysql://root:1234@127.0.0.1:3306";
        auto mysqlTask = WFTaskFactory::create_mysql_task(mysqlurl,0,
            [response](WFMySQLTask * mysqltask){
                auto mysqlresp = mysqltask->get_resp();
                int state = mysqltask->get_state();
                int error = mysqltask->get_error();
                if(state != WFT_STATE_SUCCESS) {
                    printf("error: %s\n", WFGlobal::get_error_string(state, error));
                    return;
                }
                //语法错误
                if(mysqlresp->get_packet_type() == MYSQL_PACKET_HEADER_ERROR) {
                    printf("error_code: %d, msg: %s\n",
                        mysqlresp->get_error_code(),
                        mysqlresp->get_error_msg().c_str());
                    response->set_code(-1);
					response->set_message("failed");
                    return;
                }
                using namespace protocol;
                //通过迭代器访问结果
                MySQLResultCursor cursor(mysqlresp);
                if(cursor.get_affected_rows() == 1) {
					response->set_code(0);
                    response->set_message("SUCCESS");
                    cout << "SUCCESS" << endl;
                } else {
                    response->set_code(-1);
					response->set_message("failed");
                    cout << "failed" << endl;
                }
            });
        string sql = "INSERT INTO cloudisk.tbl_user(`user_name`, `user_pwd`, `status`)"
        "VALUES('" + username + "', '" + encodedpasswd + "', 0)";
        cout << "sql:\n" << sql << endl;
        mysqlTask->get_req()->set_query(sql);
        ctx->get_series()->push_back(mysqlTask);
    }
};

void timerCallback(WFTimerTask * timerTask) {
    printf("timerCallback is running\n");
    using namespace ppconsul::agent;
    Agent * pagent = (Agent *)timerTask->user_data;
    pagent->servicePass("SignupService1");
    auto nextTask = WFTaskFactory::create_timer_task(5*1000*1000, timerCallback);
    nextTask->user_data = pagent;
    series_of(timerTask)->push_back(nextTask);
}

int main()
{
	GOOGLE_PROTOBUF_VERIFY_VERSION;
	unsigned short port = 1412;
	SRPCServer server;

	UserServiceServiceImpl userservice_impl;
    //添加用户注册的服务
	server.add_service(&userservice_impl);
    //启动服务器
	server.start(port);

    using namespace ppconsul;
    //向consul中注册服务
    Consul consul("127.0.0.1:8500", ppconsul::kw::dc = "dc1");
    agent::Agent agent(consul);

    agent.registerService(
        agent::kw::name = "SignupService1",
        agent::kw::address = "127.0.0.1",
        agent::kw::id = "SignupService1",
        agent::kw::port = 1412,
        agent::kw::check = agent::TtlCheck(std::chrono::seconds(10))
    );
    //取消注册
    //agent.deregisterService("SignupService1");
    //发送心跳
    //agent.servicePass("SignupService1");
    auto timerTask = WFTaskFactory::create_timer_task(5 * 1000 * 1000, timerCallback);
    timerTask->user_data = &agent;
    timerTask->start();

	wait_group.wait();
    //停止服务器
	server.stop();

	google::protobuf::ShutdownProtobufLibrary();
	return 0;
}
